package com.leng.web.servlet;

import java.lang.reflect.InvocationTargetException;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.leng.web.annotation.exception.HandlerNotFoundException;
import com.leng.web.annotation.exception.MissingParameterException;
import com.leng.web.annotation.exception.RequestMethodNotSupportException;
import com.leng.web.annotation.exception.resolver.HandlerExceptionResolver;
import com.leng.web.annotation.support.HandlerResolver;
import com.leng.web.context.ClassPathApplicationContext;
import com.leng.web.handler.Handler;
import com.leng.web.request.HttpServletRequest;
import com.leng.web.request.WebRequest;
import com.leng.web.util.HttpResponseUtils;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;

public class DispatcherServlet extends SimpleChannelInboundHandler<FullHttpRequest> {
	private static Logger logger = Logger.getLogger(DispatcherServlet.class);
	private static HandlerExceptionResolver resolver = null;// 统一的异常处理器

	static {
		try {
			ClassPathApplicationContext context = ClassPathApplicationContext.getInstance();
			resolver = context.getResolver();
		} catch (Exception e) {
			logger.error("获取全局异常处理器失败.", e);
		}
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
		WebRequest request = new HttpServletRequest(req);

		String message = "";
		HttpResponseStatus status = null;
		Handler handler = null;
		String contentType = "application/json";
		try {
			HandlerResolver hr = HandlerResolver.getInstance();
			handler = hr.resorveHandler(request);
			Object[] args = hr.resolveHandlerArguments(handler, request, ctx);// 绑定参数
			Object res = null;
			try {
				res = handler.invoke(args);
			} catch (Exception e) {
				if (resolver != null) {
					if (e instanceof InvocationTargetException) {
						e = (Exception) e.getCause();
					}
					resolver.resolveException(request, handler, ctx, e);
					return;
				}
				throw e;
			}
			if (handler.isShakehands()) {// 握手请求不能响应消息
				return;
			}
			if (res != null) {
				if (handler.isResponseBody()) {
					message = JSONObject.toJSONString(res);
				} else {
					contentType = "text/html;charset=UTF-8";
					message = res.toString();
				}
			}
			status = HttpResponseStatus.OK;
		} catch (HandlerNotFoundException e) {
			message = e.getMessage();
			status = HttpResponseStatus.NOT_FOUND;
			logger.error(e);
		} catch (RequestMethodNotSupportException e) {
			message = e.getMessage();
			status = HttpResponseStatus.METHOD_NOT_ALLOWED;
			logger.error(e);
		} catch (MissingParameterException e) {
			message = e.getMessage();
			status = HttpResponseStatus.BAD_REQUEST;
			logger.error(e);
		} catch (Exception e) {
			logger.error("服务器内部错误...clause=" + e.getMessage(), e);
			message = e.getMessage();
			status = HttpResponseStatus.INTERNAL_SERVER_ERROR;
		}
		HttpResponseUtils.sendHttpResponse(ctx, status, message, contentType);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
}
